home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / pobox / qu2po_send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-03-11  |  13.3 KB  |  461 lines

  1. #include "util.h"
  2. #include "mmdf.h"
  3.  
  4. /*
  5.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  6.  *
  7.  *
  8.  *     Copyright (C) 1979,1980,1981  University of Delaware
  9.  *
  10.  *     Department of Electrical Engineering
  11.  *     University of Delaware
  12.  *     Newark, Delaware  19711
  13.  *
  14.  *     Phone:  (302) 738-1163
  15.  *
  16.  *
  17.  *     This program module was developed as part of the University
  18.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  19.  *
  20.  *     Acquisition, use, and distribution of this module and its listings
  21.  *     are subject restricted to the terms of a license agreement.
  22.  *     Documents describing systems using this module must cite its source.
  23.  *
  24.  *     The above statements must be retained with all copies of this
  25.  *     program and may not be removed without the consent of the
  26.  *     University of Delaware.
  27.  *     
  28.  *
  29.  *     version  -1    David H. Crocker    March   1979
  30.  *     version   0    David H. Crocker    April   1980
  31.  *     version  v7    David H. Crocker    May     1981
  32.  *     version   1    David H. Crocker    October 1981
  33.  *
  34.  */
  35.  
  36. /*              SEND FROM DELIVER OVER TO CALLER (PASSIVE)              */
  37.  
  38. #include "ch.h"
  39. #include "chan.h"
  40. #include <pwd.h>
  41. #include "ap.h"
  42.  
  43. extern struct ll_struct    *logptr;
  44.  
  45. extern char *mmdflogin;
  46. extern char *supportaddr;
  47.  
  48. extern char *strdup();
  49. extern char *ap_p2s();
  50.  
  51. extern int ap_outtype;
  52.  
  53. LOCVAR char *sender = (char *)NULL;    /* return address for message         */
  54. LOCVAR char *adr    = (char *)NULL;    /* recipient address                  */
  55. LOCVAR struct rp_construct
  56.                 rp_hend  =
  57. {
  58.     RP_NOOP, 'e', 'n', 'd', ' ', 'o', 'f', ' ', 'h', 'o', 's', 't', ' ',
  59.     'i', 'g', 'n', 'o', 'r', 'e', 'd', '\0'
  60. };
  61. LOCVAR struct rp_construct
  62.                 rp_skip =
  63. {
  64.     RP_NOOP, 's', 'k', 'i', 'p', ' ', 't', 'h', 'i', 's', ' ',
  65.     'a', 'd', 'd', 'r', 'e', 's', 's', '\0'
  66. };
  67.  
  68. LOCVAR Chan *q2p_chan;            /* what channel am I?                 */
  69.  
  70. LOCVAR int    q2p_uid;            /* user id of caller                  */
  71.  
  72. LOCVAR unsigned short q2p_nadrs;  /* number of valid addresses          */
  73.  
  74. LOCVAR char *q2p_info;            /* initialization info for message    */
  75.  
  76. LOCVAR char q2p_username[USERSIZE + 1];
  77.                   /* name of caller                     */
  78. LOCVAR char q2p_out;              /* at least one adr sent              */
  79. char po_state = SND_RINIT;/* state of processing current msg    */
  80. /* */
  81.  
  82. qu2po_send (chname)               /* overall mngmt for batch of msgs    */
  83.     char chname[];                /* name of channel we are             */
  84. {
  85.     extern char *strdup ();
  86.     short     result;
  87.     char    info[LINESIZE],
  88.         sendbuf[ADDRSIZE];
  89.  
  90. #ifdef DEBUG
  91.     ll_log (logptr, LLOGBTR, "qu2po_send");
  92. #endif
  93.  
  94.     q2p_gcinfo ();                /* get info on the caller             */
  95.  
  96.     q2p_chan = ch_nm2struct (chname);
  97.     if (q2p_chan == (Chan *) NOTOK)
  98.     err_abrt (RP_PARM, "unknown channel name '%s'", chname);
  99.                   /* find out who I am                  */
  100.  
  101.     if (q2p_chan -> ch_login != 0)  /* only one login may pickup chan     */
  102.     {
  103. #ifdef DEBUG
  104.     ll_log (logptr, LLOGFTR, "%s =?= %s",
  105.             q2p_username, q2p_chan -> ch_login);
  106. #endif
  107.     if (!lexequ (q2p_username, q2p_chan -> ch_login) &&
  108.         !lexequ (q2p_username, mmdflogin))
  109.     {
  110.         ll_log (logptr, LLOGFAT,
  111.             "'%s' not authorized to pickup for %s (%s)",
  112.             q2p_username, q2p_chan -> ch_table -> tb_name, 
  113.             q2p_chan -> ch_name);
  114.         return (RP_USER);     /* caller not authorized to pickup    */
  115.     }
  116.     }
  117.  
  118.     if (rp_isbad (result = qu_pkinit ()))
  119.     return (result);
  120.  
  121.     if (rp_isbad (result = po_sbinit ()))
  122.     return (result);
  123.  
  124.     po_state = SND_ABORT;
  125.     for(;;){
  126.     AP_ptr  loctree, domtree, routree, sendtree;
  127.     AP_ptr  ap_s2tree(), ap_normalize();
  128.  
  129.     result = qu_rinit (info, sendbuf, q2p_chan->ch_apout);
  130.     if(rp_gval(result) == RP_NS){
  131.         qu_rend();
  132.         continue;
  133.     }
  134.     else if(rp_gval(result) == RP_DONE)
  135.         break;
  136.  
  137.     if (rp_gval(result) == RP_FIO)          /* Can't open message file */
  138.         continue;
  139.     else if (rp_gval(result) != RP_OK)      /* Some other error */
  140.         break;
  141.  
  142.     q2p_info = strdup (info); /* not sent until an address goes out */
  143.  
  144.     if (sender != (char *)NULL){
  145.         free (sender);
  146.         sender = NULL;
  147.     }
  148.  
  149.     if ( sendbuf[0] == '\0' ||
  150.         (sendtree = ap_s2tree( sendbuf )) == (AP_ptr) NOTOK) {
  151.         printx("return address unparseable, using Orphanage\n");
  152.         fflush(stdout);
  153.         if ((sendtree = ap_s2tree ( supportaddr )) == (AP_ptr) NOTOK) {
  154.             printx("Orphanage unparseable, using MMDF\n");
  155.             fflush(stdout);
  156.             if ((sendtree = ap_s2tree (mmdflogin)) == (AP_ptr) NOTOK) {
  157.             result = RP_PARM;
  158.             qu_rend();
  159.             continue;
  160.             }
  161.         }
  162.     }
  163.     ap_outtype = q2p_chan -> ch_apout;
  164.     sendtree = ap_normalize (q2p_chan -> ch_lname,
  165.                q2p_chan  -> ch_ldomain, sendtree, q2p_chan);
  166.     if(sendtree == (AP_ptr)MAYBE){
  167.         qu_rend();
  168.         continue;
  169.     }
  170.     ap_t2parts (sendtree, (AP_ptr *)0, (AP_ptr *)0, &loctree, &domtree, &routree);
  171.     sender = ap_p2s ((AP_ptr)0, (AP_ptr)0, loctree, domtree, routree);
  172.     if(sender == (char *)MAYBE){
  173.         qu_rend();          
  174.         continue;
  175.     }
  176.     ap_sqdelete( sendtree, (AP_ptr) 0 );
  177.     ap_free( sendtree );
  178.  
  179.     po_state = SND_RDADR;
  180.     if (rp_isbad (result = q2p_admng ()))
  181.         return (result);      /* send the address list              */
  182.  
  183.     if (rp_gval (result) != RP_DONE)
  184.         break;                /* catch protocol errors              */
  185.  
  186.     result = q2p_txmng ();
  187.     free (q2p_info);          /* don't have to zero                 */
  188.     if (rp_isbad (result))
  189.         return (result);      /* send the message text              */
  190.     }
  191.  
  192.     if (rp_gval (result) != RP_DONE)
  193.     {
  194.     ll_log (logptr, LLOGTMP, "not DONE (%s)", rp_valstr (result));
  195.     return (RP_RPLY);         /* catch protocol errors              */
  196.     }
  197.  
  198.     po_state = SND_ABORT;
  199.     qu_pkend ();                  /* done getting messages              */
  200.     return (po_sbend ());         /* done sending messages              */
  201. }
  202. /* */
  203.  
  204. LOCFUN
  205.     q2p_admng ()              /* send address list                  */
  206. {
  207.     struct rp_bufstruct thereply;
  208.     short     result;
  209.     int       len;
  210.     char    host[ADDRSIZE];
  211.     char    adrbuf[ADDRSIZE];
  212.  
  213.     AP_ptr  loctree, domtree, routree, adrtree;
  214.     AP_ptr  ap_s2tree(), ap_normalize();
  215.  
  216.  
  217. #ifdef DEBUG
  218.     ll_log (logptr, LLOGBTR, "q2p_admng");
  219. #endif
  220.  
  221.     q2p_nadrs = 0;                /* reset for each new messages        */
  222.     q2p_out = FALSE;
  223.     FOREVER                       /* iterate thru list                  */
  224.     {                             /* we already have and adr            */
  225.     po_state = SND_ABORT;
  226.     result = qu_radr (host, adrbuf);
  227.     if (rp_isbad (result))
  228.         return (result);      /* get address from Deliver           */
  229.  
  230.     if (rp_gval (result) == RP_HOK)
  231.     {                         /* no-op the sub-list indication      */
  232.         qu_wrply ((struct rp_bufstruct *) &rp_hend, rp_conlen (rp_hend));
  233.         continue;
  234.     }
  235.  
  236.     if (rp_gval (result) == RP_DONE)
  237.         break;                /* end of address list                */
  238.  
  239.     po_state = SND_ARPLY;
  240.     if (!q2p_mayadr (host))
  241.     {                         /* not authorized to go out           */
  242.         qu_wrply ((struct rp_bufstruct *) &rp_skip, rp_conlen (rp_skip));
  243.         continue;
  244.     }
  245.  
  246.     if (!q2p_out)             /* first one to go out                */
  247.     {
  248.         q2p_out = TRUE;
  249.         if (rp_isbad (result =
  250.                 po_winit ((char *) 0, q2p_info, sender)))
  251.         return (result);
  252.     }
  253.  
  254.     if (adr != (char *)NULL)
  255.         free (adr);
  256.  
  257.     if ( (adrtree = ap_s2tree(adrbuf)) == (AP_ptr) NOTOK)  {
  258.         adr = strdup( adrbuf );
  259.     } else {
  260.         ap_outtype = q2p_chan -> ch_apout;
  261.         adrtree = ap_normalize (q2p_chan -> ch_lname,
  262.                 q2p_chan  -> ch_ldomain, adrtree, q2p_chan);
  263.         if(adrtree == (AP_ptr)MAYBE)
  264.             return(RP_NS);
  265.         ap_t2parts (adrtree, (AP_ptr *)0, (AP_ptr *)0, &loctree, &domtree, &routree);
  266.         adr = ap_p2s ((AP_ptr)0, (AP_ptr)0, loctree, domtree, routree);
  267.         if(adr == (char *)MAYBE)
  268.             return(RP_NS);
  269.         ap_sqdelete( adrtree, (AP_ptr) 0 );
  270.         ap_free( adrtree );
  271.       }
  272.  
  273.     if (rp_isbad (result = po_wadr (host, adr)))
  274.         return (result);      /* give to remote site                */
  275.  
  276.     if (rp_isbad (result = po_rrply (&thereply, &len)))
  277.         return (result);      /* how did remote like it?            */
  278.  
  279.     switch (rp_gval (thereply.rp_val))
  280.     {                         /* was address acceptable?            */
  281.         case RP_AOK:          /* address ok, text not yet sent      */
  282.         q2p_nadrs++;
  283.         po_state = SND_ABORT;
  284.         qu_wrply (&thereply, len);
  285.         break;
  286.  
  287.         case RP_NO:           /* remaining acceptible responses     */
  288.         thereply.rp_val = RP_NDEL;
  289.         case RP_USER: 
  290.         case RP_NDEL: 
  291.         case RP_AGN: 
  292.         case RP_NOOP: 
  293.         po_state = SND_ABORT;
  294.         qu_wrply (&thereply, len);
  295.         break;
  296.  
  297.         default:              /* responses which force abort        */
  298.         if (rp_isbad (thereply.rp_val))
  299.             return (thereply.rp_val);
  300.         return (RP_RPLY);
  301.     }
  302.     }
  303.     po_state = SND_TRPLY;
  304.     if (q2p_out)                  /* at least one went out              */
  305.     return (po_waend ());    /* tell remote of address list end    */
  306.     else
  307.     return (RP_DONE);
  308. }
  309. /* */
  310.  
  311. LOCFUN
  312.     q2p_txmng ()              /* send message text                  */
  313. {
  314.     struct rp_bufstruct thereply;
  315.     int     len;
  316.     short   result;
  317.     char    buffer[BUFSIZ];
  318.     static char faktxt[] = "   ";       /* to keep dial happy   */
  319.  
  320. /*  the main portion handles normal transmission, when there have been
  321.  *  some addresses accepted.  when no addresses have been accepted, then
  322.  *  the text will be ignored by the receiving side.
  323.  */
  324. #ifdef DEBUG
  325.     ll_log (logptr, LLOGBTR, "q2p_txmng");
  326. #endif
  327.  
  328.     if (!q2p_out)
  329.     {                             /* no addresses tried                 */
  330.     ll_log (logptr, LLOGGEN, "no addrs sent");
  331.     qu_wrply ((struct rp_bufstruct *) &rp_skip, rp_conlen (rp_skip));
  332.     return (RP_OK);
  333.     }
  334.  
  335.     if (q2p_nadrs == 0)           /* no valid addresses                 */
  336.     {                             /* send some text to keep things happy*/
  337.     if (rp_isbad (result = po_wtxt (faktxt, (sizeof faktxt) - 1)))
  338.         return (result);
  339.     if (rp_gval (result) != RP_OK)
  340.         return (RP_RPLY);
  341.     }
  342.     else
  343.     {
  344.     qu_rtinit (0L);           /* get ready to read text             */
  345.         len = sizeof(buffer);
  346.     while ((rp_gval (result = qu_rtxt (buffer, &len))) == RP_OK)
  347.     {
  348.         if (rp_isbad (result = po_wtxt (buffer, len)))
  349.         return (result);
  350.         if (rp_gval (result) != RP_OK)
  351.         return (RP_RPLY);
  352.         len = sizeof(buffer);
  353.     }
  354.  
  355.     if (rp_isbad (result))
  356.         return (result);
  357.     if (rp_gval (result) != RP_DONE)
  358.         return (RP_RPLY);     /* didn't get it all across?          */
  359.     }
  360.  
  361.  
  362.     if (rp_isbad (result = po_wtend ()))
  363.     return (result);          /* flag end of message                */
  364.  
  365.     if (rp_isbad (result = po_rrply (&thereply, &len)))
  366.     return (result);          /* problem getting reply?             */
  367.  
  368.     switch (rp_gval (thereply.rp_val))
  369.     {                             /* was text acceptable?               */
  370.     case RP_OK: 
  371.         thereply.rp_val = RP_MOK;
  372.     case RP_MOK:              /* text was accepted                  */
  373.         qu_wrply (&thereply, len);
  374.         break;
  375.  
  376.     case RP_NO:               /* remaining acceptible responses     */
  377.         thereply.rp_val = RP_NDEL;
  378.     case RP_NDEL: 
  379.     case RP_AGN: 
  380.     case RP_NOOP: 
  381.         qu_wrply (&thereply, len);
  382.         break;
  383.  
  384.     default:                  /* responses which force abort        */
  385.         if (rp_isbad (thereply.rp_val))
  386.         return (thereply.rp_val);
  387.         return (RP_RPLY);
  388.     }
  389.     return (thereply.rp_val);     /* just quote remote                  */
  390. }
  391. /* */
  392.  
  393. LOCFUN
  394.     q2p_gcinfo ()             /* who is the caller?                 */
  395. {
  396.     struct passwd *getpwuid ();
  397.     int   effecid;
  398.     register struct passwd  *pwdptr;
  399.  
  400. #ifdef DEBUG
  401.     ll_log (logptr, LLOGBTR, "q2p_gcinfo ()");
  402. #endif
  403.  
  404.     getwho (&q2p_uid, &effecid);
  405.     pwdptr = getpwuid (q2p_uid);
  406.  
  407.     strcpy (q2p_username, pwdptr -> pw_name);
  408. }
  409. /* */
  410.  
  411. LOCFUN
  412.     q2p_mayadr (host)         /* may caller get this message?       */
  413. char    host[];                   /* destination host                   */
  414. {
  415.     char    adrline[LINESIZE];
  416.  
  417. #ifdef DEBUG
  418.     ll_log (logptr, LLOGBTR, "q2p_mayadr");
  419. #endif
  420.  
  421. /* PICKUP POLICY:   Who may pickup messages?
  422.  *
  423.  *  Two situations will be most common:  pickup net & relay
  424.  *
  425.  *  A "pickup net" is a network of callers who each will have
  426.  *  mail to pickup.  Each caller is a single recipient (machine).
  427.  *  Hence, a "host" equates to a single receiver (machine).  The
  428.  *  hostname, therefore, must equal the name (unix login name) of
  429.  *  the caller.
  430.  *
  431.  *  A "relay" is a single caller, retrieving mail for a set of
  432.  *  hosts.  Here, the hostname has nothing to do with the
  433.  *  caller's id and is part of the address that is passed on.
  434.  *  (For local, arpanet, and pickup-net mail, the hostname part
  435.  *  of the address is not passed on to the recipient.)  In this
  436.  *  case, the id of the authorized caller is hard-wired into a
  437.  *  variable.
  438.  *
  439.  *  The authorization test, for relaying, is done in qu2ph_send's
  440.  *  startup.  The test for pickup-net is done in this routine.
  441.  */
  442.  
  443.     if (q2p_chan -> ch_login == 0)
  444.     {                             /* login => host, not chan            */
  445.     if (tb_k2val (q2p_chan -> ch_table, TRUE, host, adrline)!=OK)
  446.     {
  447.         ll_log (logptr, LLOGTMP, "pobox host '%s' not in table!", host);
  448.         return (FALSE);       /* map name -> address                  */
  449.     }
  450.  
  451. #ifdef DEBUG
  452.     ll_log (logptr, LLOGFTR, "%s =?= %s", adrline, q2p_username);
  453. #endif
  454.  
  455.     if (!lexequ (adrline, q2p_username))
  456.         return (FALSE);       /* "address" == this user's id?         */
  457.     }
  458.  
  459.     return (TRUE);                /* OK to send                           */
  460. }
  461.